﻿using ConsoleApp1;
using System;
using System.Collections.Generic;

public class Program
{
    private static string[] cardNames = {"Card_1_1","Card_1_2","Card_1_3","Card_1_4","Card_1_5","Card_1_6","Card_1_7","Card_1_8","Card_1_9","Card_1_10","Card_1_11","Card_1_12","Card_1_13",
"Card_2_1","Card_2_2","Card_2_3","Card_2_4","Card_2_5","Card_2_6","Card_2_7","Card_2_8","Card_2_9","Card_2_10","Card_2_11","Card_2_12","Card_2_13",
"Card_3_1","Card_3_2","Card_3_3","Card_3_4","Card_3_5","Card_3_6","Card_3_7","Card_3_8","Card_3_9","Card_3_10","Card_3_11","Card_3_12","Card_3_13",
"Card_4_1","Card_4_2","Card_4_3","Card_4_4","Card_4_5","Card_4_6","Card_4_7","Card_4_8","Card_4_9","Card_4_10","Card_4_11","Card_4_12","Card_4_13"};  //所有牌集合

    public static CardManagerStates cardManagerState = CardManagerStates.None;

    private static List<CardInfo> computerResultCards = new List<CardInfo>();
    private static List<CardInfo> playerResultCards = new List<CardInfo>();

    private static List<int> heartsL = new List<int>();
    private static List<int> spadesL = new List<int>();
    private static List<int> diamondsL = new List<int>();
    private static List<int> clubsL = new List<int>();

    public static void Main()
    {

        ClearCards();
        ShuffleCards();

        OnCompareTermClick();
    }

    public static void ShuffleCards()
    {
        //进入洗牌阶段
        cardManagerState = CardManagerStates.Ready;
        cardNames = cardNames.OrderBy(c => Guid.NewGuid()).ToArray();

        computerResultCards.Add(new CardInfo(cardNames[0]));
        computerResultCards.Add(new CardInfo(cardNames[1]));
        computerResultCards.Add(new CardInfo(cardNames[3]));
        computerResultCards.Add(new CardInfo(cardNames[4]));
        computerResultCards.Add(new CardInfo(cardNames[6]));
        computerResultCards.Add(new CardInfo(cardNames[7]));
        computerResultCards.Add(new CardInfo(cardNames[8]));

        playerResultCards.Add(new CardInfo(cardNames[1]));
        playerResultCards.Add(new CardInfo(cardNames[2]));
        playerResultCards.Add(new CardInfo(cardNames[4]));
        playerResultCards.Add(new CardInfo(cardNames[5]));
        playerResultCards.Add(new CardInfo(cardNames[6]));
        playerResultCards.Add(new CardInfo(cardNames[7]));
        playerResultCards.Add(new CardInfo(cardNames[8]));

        cardManagerState = CardManagerStates.FiveCard;
    }

    public static void ClearCards()
    {
        cardManagerState = CardManagerStates.Ready;
    }

    public static void OnCompareTermClick()
    {
        //
        if (cardManagerState == CardManagerStates.FiveCard)
        {
            cardManagerState = CardManagerStates.JieSuan;

            int win = compareResult();
            Console.WriteLine("win =" + win);
        }
        if (cardManagerState == CardManagerStates.JieSuan)
        {
            Console.WriteLine("now in JieSuan state!");
        }
    }

    public static void preAnalysLocal(List<CardInfo> cardinfol)
    {
        heartsL.Clear();
        spadesL.Clear();
        diamondsL.Clear();
        clubsL.Clear();

        for (int i = 0; i < cardinfol.Count; i++)
        {
            switch (cardinfol[i].cardType)
            {
                case CardTypes.Hearts:
                    heartsL.Add(cardinfol[i].cardIndex);
                    break;
                case CardTypes.Spades:
                    spadesL.Add(cardinfol[i].cardIndex);
                    break;
                case CardTypes.Diamonds:
                    diamondsL.Add(cardinfol[i].cardIndex);
                    break;
                case CardTypes.Clubs:
                    clubsL.Add(cardinfol[i].cardIndex);
                    break;
            }
        }
        heartsL.Sort();
        spadesL.Sort();
        diamondsL.Sort();
        clubsL.Sort();
    }

    private static int compareResult()
    {
        CheckResult computerResult = chechRoyalStraightSameType(computerResultCards);
        if (computerResult.valueType == FollowCardsTypes.Single)
        {
            computerResult = checkStraightSameType(computerResultCards);
            if (computerResult.valueType == FollowCardsTypes.Single)
            {
                computerResult = checkFour(computerResultCards);
                if (computerResult.valueType == FollowCardsTypes.Single)
                {
                    computerResult = checkGourd(computerResultCards);
                    if (computerResult.valueType == FollowCardsTypes.Single)
                    {
                        computerResult = checkSameType(computerResultCards);
                        if (computerResult.valueType == FollowCardsTypes.Single)
                        {
                            computerResult = checkStraightDifType(computerResultCards);
                            if (computerResult.valueType == FollowCardsTypes.Single)
                            {
                                computerResult = checkThreeOneOne(computerResultCards);
                                if (computerResult.valueType == FollowCardsTypes.Single)
                                {
                                    computerResult = checkTwoDouble(computerResultCards);
                                    if (computerResult.valueType == FollowCardsTypes.Single)
                                    {
                                        computerResult = checkDouble(computerResultCards);
                                        if (computerResult.valueType == FollowCardsTypes.Single)
                                        {
                                            computerResult = checkSingle(computerResultCards);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        CheckResult playerResult = chechRoyalStraightSameType(playerResultCards);
        if (playerResult.valueType == FollowCardsTypes.Single)
        {
            playerResult = checkStraightSameType(playerResultCards);
            if (playerResult.valueType == FollowCardsTypes.Single)
            {
                playerResult = checkFour(playerResultCards);
                if (playerResult.valueType == FollowCardsTypes.Single)
                {
                    playerResult = checkGourd(playerResultCards);
                    if (playerResult.valueType == FollowCardsTypes.Single)
                    {
                        playerResult = checkSameType(playerResultCards);
                        if (playerResult.valueType == FollowCardsTypes.Single)
                        {
                            playerResult = checkStraightDifType(playerResultCards);
                            if (playerResult.valueType == FollowCardsTypes.Single)
                            {
                                playerResult = checkThreeOneOne(playerResultCards);
                                if (playerResult.valueType == FollowCardsTypes.Single)
                                {
                                    playerResult = checkTwoDouble(playerResultCards);
                                    if (playerResult.valueType == FollowCardsTypes.Single)
                                    {
                                        playerResult = checkDouble(playerResultCards);
                                        if (playerResult.valueType == FollowCardsTypes.Single)
                                        {
                                            playerResult = checkSingle(playerResultCards);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return playerResult.CompareTo(computerResult);
    }

    private static CheckResult chechRoyalStraightSameType(List<CardInfo> cardinfol)
    {
        preAnalysLocal(cardinfol);

        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        if (heartsL.Count >= 5 && if_sequence(heartsL))
        {
            if (heartsL[heartsL.Count - 1] == 12)
            {
                result.valueType = FollowCardsTypes.RoyalStraightSameType;
                result.cardType = CardTypes.Hearts;
            }
        }

        if (spadesL.Count >= 5 && if_sequence(spadesL))
        {
            if (spadesL[spadesL.Count - 1] == 12)
            {
                result.valueType = FollowCardsTypes.RoyalStraightSameType;
                result.cardType = CardTypes.Spades;
            }
        }

        if (diamondsL.Count >= 5 && if_sequence(diamondsL))
        {
            if (diamondsL[diamondsL.Count - 1] == 12)
            {
                result.valueType = FollowCardsTypes.RoyalStraightSameType;
                result.cardType = CardTypes.Diamonds;
            }
        }

        if (clubsL.Count >= 5 && if_sequence(clubsL))
        {
            if (clubsL[clubsL.Count - 1] == 12)
            {
                result.valueType = FollowCardsTypes.RoyalStraightSameType;
                result.cardType = CardTypes.Clubs;
            }
        }

        return result;
    }

    private static CheckResult checkStraightSameType(List<CardInfo> cardinfol)
    {

        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;
        int max = 3;

        preAnalysLocal(cardinfol);

        if (heartsL.Count >= 5 && if_sequence(heartsL))
        {
            if (heartsL[heartsL.Count - 1] > max)
            {
                max = heartsL[heartsL.Count - 1];
                result.cardType = CardTypes.Hearts;
                result.valueType = FollowCardsTypes.StraightSameType;
                result.max = max;
            }
        }

        if (spadesL.Count >= 5 && if_sequence(spadesL))
        {
            if (spadesL[spadesL.Count - 1] > max)
            {
                max = spadesL[spadesL.Count - 1];
                result.cardType = CardTypes.Spades;
                result.valueType = FollowCardsTypes.StraightSameType;
                result.max = max;
            }
        }

        if (diamondsL.Count >= 5 && if_sequence(diamondsL))
        {
            if (diamondsL[diamondsL.Count - 1] > max)
            {
                max = diamondsL[diamondsL.Count - 1];
                result.cardType = CardTypes.Diamonds;
                result.valueType = FollowCardsTypes.StraightSameType;
                result.max = max;
            }
        }

        if (clubsL.Count >= 5 && if_sequence(clubsL))
        {
            if (clubsL[clubsL.Count - 1] > max)
            {
                max = clubsL[clubsL.Count - 1];
                result.cardType = CardTypes.Clubs;
                result.valueType = FollowCardsTypes.StraightSameType;
                result.max = max;
            }
        }

        return result;
    }

    private static CheckResult checkFour(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        preAnalysLocal(cardinfol);

        Dictionary<int, int> hashMap = new Dictionary<int, int>();
        foreach (CardInfo ci in cardinfol)
        {
            if (!hashMap.ContainsKey(ci.cardIndex))
            {
                hashMap.Add(ci.cardIndex, 1);
            }
            else
            {
                hashMap[ci.cardIndex] += 1;
            }
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 4)
            {
                result.valueType = FollowCardsTypes.Four;
                result.max = kvp.Key;
            }
        }

        return result;
    }

    private static CheckResult checkGourd(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        preAnalysLocal(cardinfol);

        int threetimes = 0;
        int threemax = 0;
        int threesecmax = 0;
        int twotimes = 0;
        int twomax = 0;
        int twosec = 0;

        Dictionary<int, int> hashMap = new Dictionary<int, int>();
        foreach (CardInfo ci in cardinfol)
        {
            if (!hashMap.ContainsKey(ci.cardIndex))
            {
                hashMap.Add(ci.cardIndex, 1);
            }
            else
            {
                hashMap[ci.cardIndex] += 1;
            }
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 3)
            {
                threetimes++;
                if (threetimes == 2 && threemax < kvp.Key)
                {
                    threesecmax = threemax;
                    threemax = kvp.Key;
                }
                if (threetimes == 1 && threemax < kvp.Key)
                {
                    threemax = kvp.Key;
                };
            }
            if (kvp.Value == 2)
            {
                twotimes++;
                if (twomax < kvp.Key)
                {
                    twomax = kvp.Key;
                };
            }
        }
        if (threetimes == 2)
        {
            result.valueType = FollowCardsTypes.Gourd;
            result.max = threemax;
            result.secmax = threesecmax;
        }
        if (threetimes == 1 && twotimes == 1)
        {
            result.valueType = FollowCardsTypes.Gourd;
            result.max = threemax;
            result.secmax = twomax;
        }

        return result;
    }

    private static CheckResult checkSameType(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        preAnalysLocal(cardinfol);

        if (heartsL.Count >= 5 || spadesL.Count >= 5 || diamondsL.Count >= 5 || clubsL.Count >= 5)
        {
            result.valueType = FollowCardsTypes.SameType;
            if (heartsL.Count >= 5)
            {
                result.max = getMax(heartsL);
            }
            if (spadesL.Count >= 5)
            {
                result.max = getMax(spadesL);
            }
            if (diamondsL.Count >= 5)
            {
                result.max = getMax(diamondsL);
            }
            if (clubsL.Count >= 5)
            {
                result.max = getMax(clubsL);
            }
        }

        return result;
    }

    private static CheckResult checkStraightDifType(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        List<int> tmp = new List<int>();

        for (int i = 0; i < cardinfol.Count; i++)
        {
            tmp.Add(cardinfol[i].cardIndex);
        }
        tmp.Sort();
        for (int start = 2; start >= 0; start--)
        {
            List<int> subList = tmp.Where((value, index) => index >= start && index <= start + 4)
                                .ToList();
            if (if_sequence(subList))
            {
                result.valueType = FollowCardsTypes.StraightDifType;
                result.max = subList[4];
                break;
            }
        }

        return result;
    }

    private static CheckResult checkThreeOneOne(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        int threetimes = 0;
        int threemax = 0;
        int onemax = 0;
        int onesecmax = 0;

        Dictionary<int, int> hashMap = new Dictionary<int, int>();
        foreach (CardInfo ci in cardinfol)
        {
            if (!hashMap.ContainsKey(ci.cardIndex))
            {
                hashMap.Add(ci.cardIndex, 1);
            }
            else
            {
                hashMap[ci.cardIndex] += 1;
            }
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 3)
            {
                threetimes++;
                if (threemax < kvp.Key)
                {
                    threemax = kvp.Key;
                };
            }
        }

        if (threetimes == 1)
        {
            result.valueType = FollowCardsTypes.ThreeOneOne;
            result.max = threemax;
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 1)
            {
                if (onemax < kvp.Key)
                {
                    onesecmax = onemax;
                    onemax = kvp.Key;
                };
            }
        }

        result.secmax = onemax;
        result.thirmax = onesecmax;

        return result;
    }

    private static CheckResult checkTwoDouble(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        int towtimes = 0;
        int towmax = 0;
        int onemax = 0;
        int towsecmax = 0;

        Dictionary<int, int> hashMap = new Dictionary<int, int>();
        foreach (CardInfo ci in cardinfol)
        {
            if (!hashMap.ContainsKey(ci.cardIndex))
            {
                hashMap.Add(ci.cardIndex, 1);
            }
            else
            {
                hashMap[ci.cardIndex] += 1;
            }
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 2)
            {
                towtimes++;
                if (towtimes == 2 && towmax < kvp.Key)
                {
                    towsecmax = towmax;
                    towmax = kvp.Key;
                }
            }
        }

        if (towtimes == 2)
        {
            result.valueType = FollowCardsTypes.TwoDouble;
            result.max = towmax;
            result.secmax = towsecmax;
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 1)
            {
                if (onemax < kvp.Key)
                {
                    onemax = kvp.Key;
                };
            }
        }
        result.thirmax = onemax;

        return result;
    }

    private static CheckResult checkDouble(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        int towtimes = 0;
        int towmax = 0;
        int onemax = 0;
        int onesecmax = 0;
        int onethirmax = 0;

        Dictionary<int, int> hashMap = new Dictionary<int, int>();
        foreach (CardInfo ci in cardinfol)
        {
            if (!hashMap.ContainsKey(ci.cardIndex))
            {
                hashMap.Add(ci.cardIndex, 1);
            }
            else
            {
                hashMap[ci.cardIndex] += 1;
            }
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 2)
            {
                towtimes++;
                if (towmax < kvp.Key)
                {
                    towmax = kvp.Key;
                }
            }
        }

        if (towtimes == 1)
        {
            result.valueType = FollowCardsTypes.Double;
            result.max = towmax;
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 1)
            {
                if (onemax < kvp.Key)
                {
                    onethirmax = onesecmax;
                    onesecmax = onemax;
                    onemax = kvp.Key;
                };
            }
        }
        result.secmax = onemax;
        result.thirmax = onesecmax;
        result.fourmax = onethirmax;

        return result;
    }

    private static CheckResult checkSingle(List<CardInfo> cardinfol)
    {
        CheckResult result = new CheckResult();
        result.valueType = FollowCardsTypes.Single;

        int max = 0;
        int onemax = 0;
        int onesecmax = 0;
        int onethirmax = 0;
        int onefourmax = 0;

        Dictionary<int, int> hashMap = new Dictionary<int, int>();
        foreach (CardInfo ci in cardinfol)
        {
            if (!hashMap.ContainsKey(ci.cardIndex))
            {
                hashMap.Add(ci.cardIndex, 1);
            }
            else
            {
                hashMap[ci.cardIndex] += 1;
            }
        }

        foreach (KeyValuePair<int, int> kvp in hashMap)
        {
            if (kvp.Value == 1)
            {
                if (max < kvp.Key)
                {
                    onefourmax = onethirmax;
                    onethirmax = onesecmax;
                    onesecmax = onemax;
                    onemax = max;
                    max = kvp.Key;
                };
            }
        }
        result.max = max;
        result.secmax = onemax;
        result.thirmax = onesecmax;
        result.fourmax = onethirmax;
        result.fifmax = onefourmax;

        return result;
    }


    private static bool if_sequence(List<int> arr)
    {
        int max = 0;
        int min = 12;
        for (int i = 0; i < arr.Count; i++)
        {
            if (arr[i] >= 0)
            {
                if (arr[i] >= max || 0 == max) max = arr[i];
                if (arr[i] < min || 65525 == min) min = arr[i];
            }
        }
        if (max - min > arr.Count - 1) return false;
        else return true;
    }

    private static int getMax(List<int> arr)
    {
        int max = 0;

        for (int i = 0; i < arr.Count; i++)
        {
            if (arr[i] >= max)
            {
                max = arr[i];
            }
        }
        return max;
    }



}
